package com.youhome.controller;

import com.alibaba.fastjson.JSON;
import com.aliyun.oss.OSSClient;
import com.github.pagehelper.PageInfo;
import com.youhome.config.OSSConfig;
import com.youhome.config.USAConfig;
import com.youhome.model.*;
import com.youhome.response.*;
import com.youhome.result.HomeJunction;
import com.youhome.result.SchoolDetail;
import com.youhome.service.*;
import com.youhome.utils.DateUtils;
import com.youhome.utils.OSSUtil;
import com.youhome.utils.StateUtils;
import com.youhome.utils.StringUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import net.sf.json.JSONException;
import net.sf.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@RestController
@RequestMapping(value = "/report")
@Api(tags = "报告")
public class ReportController {

    @Autowired
    USAConfig USAConfig;

    @Autowired
    private ZipService zipService;

    @Autowired
    private UnemploymentService unemploymentService;
    @Autowired
    private TruliaDataService truliaDataService;
    @Autowired
    private HouseService listHubService;
    @Autowired
    private CityDataService cityDataService;
    @Autowired
    private OSSConfig ossConfig;
    @Autowired
    private TranslateService translateService;
    @Autowired
    private SchoolService schoolService;
    @Autowired
    private HomeJunctionService homeJunctionService;
    @Autowired
    private DownloadService downloadService;

    /**
     * 房源介绍
     *
     * @param houseId
     * @return
     */
    @ApiOperation(value = "房源介绍", notes = "房源介绍", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "String", name = "houseId", value = "房源ID", required = true, paramType = "path")
    })
    @GetMapping(value = "/listings/{houseId}")
    public Object Listings(@PathVariable String houseId) {
        House listHub = listHubService.selectByPrimaryKey(houseId);
        //System.err.println(listHub.toString());
        if (listHub != null && !StringUtils.isEmpty(listHub.getListingKey())) {
            String key = "json/" + listHub.getListingKey() + ".json";
            try {
                OSSClient ossClient = new OSSClient(ossConfig.getEndpoint(), ossConfig.getAccessKeyId(), ossConfig.getAccessKeySecret());
                String json = OSSUtil.downloadJson(ossClient, ossConfig.getBacketName(), key);
                if (!StringUtils.isEmpty(json)) {
                    JSONObject dataJson = JSONObject.fromObject(json);
                    if (dataJson.get("listingDescription") != null && !dataJson.get("listingDescription").equals("null")) {
                        String listingDescription = (String) dataJson.get("listingDescription");
                        TranslationResult translationResult = translateService.trans(houseId, listingDescription);
                        return new Result(ResultCode.SUCCESS, translationResult);
                    } else {
                        return new Result(ResultCode.NO_DATA_WAS_FOUND);
                    }
                }
            } catch (JSONException e) {
                e.printStackTrace();
                return new Result(ResultCode.FAIL);
            }
        } else {
            return new Result(ResultCode.NO_DATA_WAS_FOUND);
        }
        return new Result(ResultCode.FAIL);
    }

    @ApiOperation(value = "房源价值/zipcode均价(此房源价格与附近价格对比)", notes = "房源价值/zipcode均价(此房源价格与附近价格对比)", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "String", name = "houseId", value = "房源ID", required = true, paramType = "path")
    })
    @GetMapping(value = "/housepricescomparewithaverage/{houseId}")
    public Object HousePricesCompareWithAverage(@PathVariable String houseId) {
        try {
            if (StringUtils.isEmpty(houseId)) {
                return new Result(ResultCode.ERROR_PARAMETER);
            }
            try {
                House house = listHubService.selectByPrimaryKey(houseId);

                if (house == null)
                    return new Result(ResultCode.NO_DATA_WAS_FOUND);
                Double price = house.getListPrice(); //房产价格

                String zip = house.getZip();  //邮编
                if (StringUtils.isEmpty(zip))
                    return new Result(ResultCode.NO_DATA_WAS_FOUND);
                TruliaData truliaData = truliaDataService.selectByZipcode(zip);
                if (truliaData == null)
                    return new Result(ResultCode.NO_DATA_WAS_FOUND);
                Double median_sales_price = truliaData.getMedianSalesPrice();  //房产售价中位数
                Double ratio = Double.valueOf(0);
                if (median_sales_price != null && median_sales_price != 0)
                    ratio = price / median_sales_price;

                HousePriceMedianSalesPriceRatio housePrice_medianSalesPrice_ratio = new HousePriceMedianSalesPriceRatio();
                housePrice_medianSalesPrice_ratio.setPrice(price);
                housePrice_medianSalesPrice_ratio.setMedianSalesPrice(median_sales_price);
                housePrice_medianSalesPrice_ratio.setRatio(ratio);

                return new Result(ResultCode.SUCCESS, housePrice_medianSalesPrice_ratio);
            } catch (IOException e) {
                e.printStackTrace();
                return new Result(ResultCode.NO_DATA_WAS_FOUND);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return new Result(ResultCode.FAIL);
        }
    }

    @ApiOperation(value = "房源每平方英尺均价/zipcode每平方英尺均价", notes = "房源每平方英尺均价/zipcode每平方英尺均价", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "String", name = "houseId", value = "房源ID", required = true, paramType = "path")
    })
    @GetMapping(value = "/housepricescomparewithaveragesqft/{houseId}")
    public Object HousePricesCompareWithAverageSQFT(@PathVariable String houseId) {
        if (StringUtils.isEmpty(houseId)) {
            return new Result(ResultCode.ERROR_PARAMETER);
        }
        try {
            try {
                House house = listHubService.selectByPrimaryKey(houseId);
                if (house == null)
                    return new Result(ResultCode.NO_DATA_WAS_FOUND);
                Double price = house.getListPrice(); //房产价格
                Double area = house.getLivingArea();
                if (area == null || area == 0) {
                    return new Result(ResultCode.NO_DATA_WAS_FOUND);
                }

                Double pricePerSqFt = Double.valueOf(price / area); // 房产每平方英尺单价


                String zip = house.getZip();  //邮编

                TruliaData truliaData = truliaDataService.selectByZipcode(zip);
                if (truliaData == null)
                    return new Result(ResultCode.NO_DATA_WAS_FOUND);
                Double city_pricePerSqFt = truliaData.getPricePerSqft(); //每平方英尺单价
                Double ratio = Double.valueOf(0);
                if (city_pricePerSqFt != null && city_pricePerSqFt != 0)
                    ratio = pricePerSqFt / city_pricePerSqFt;

                HousePriceMedianSalesPriceRatio housePrice_medianSalesPrice_ratio = new HousePriceMedianSalesPriceRatio();
                housePrice_medianSalesPrice_ratio.setPrice(pricePerSqFt);
                housePrice_medianSalesPrice_ratio.setMedianSalesPrice(city_pricePerSqFt);
                housePrice_medianSalesPrice_ratio.setRatio(ratio);

                return new Result(ResultCode.SUCCESS, housePrice_medianSalesPrice_ratio);
            } catch (IOException e) {
                e.printStackTrace();
                return new Result(ResultCode.NO_DATA_WAS_FOUND);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return new Result(ResultCode.FAIL);
        }
    }

    @ApiOperation(value = "zipcode 房价预测", notes = "zipcode 房价预测", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "String", name = "zipcode", value = "邮编", required = true, paramType = "path")
    })
    @GetMapping(value = "/homevalueforecast/{zipcode}")
    public Object homeValueForecast(@PathVariable("zipcode") String zipcode) {

        try {
            Zip zip = zipService.selectByPrimaryKey(zipcode);
            if (StringUtils.isEmpty(zip.getState()) || StringUtils.isEmpty(zip.getZipcode())) {
                return new Result(ResultCode.NO_DATA_WAS_FOUND);
            }
            String key = "zillow/AllRegionsForePublic/" + zip.getState().toLowerCase() + "_zip_" + zip.getZipcode() + ".json";
            System.err.println("key:" + key);
            String json = downloadService.downloadJsonFromOSS(key);
            //没有数据
            if (StringUtils.isEmpty(json)) {
                return new Result(ResultCode.NO_DATA_WAS_FOUND);
            }
            com.alibaba.fastjson.JSONObject jsonObject = JSON.parseObject(json);
            //ForecastYoYPctChange  不存在
            if (jsonObject.get("ForecastYoYPctChange") == null) {
                return new Result(ResultCode.NO_DATA_WAS_FOUND);
            }
            Double rise = Double.valueOf(jsonObject.getString("ForecastYoYPctChange"));

            TruliaData truliaData = truliaDataService.selectByZipcode(zipcode);
            if (truliaData == null)
                return new Result(ResultCode.NO_DATA_WAS_FOUND);

            Double price = truliaData.getMedianSalesPrice();

            if (rise == null || price == null)
                return new Result(ResultCode.NO_DATA_WAS_FOUND);

            Double forecastPrice = price * (1 + rise / 100);
            PriceForecast priceForecast = new PriceForecast();
            priceForecast.current_price = price;
            priceForecast.forecast_price = forecastPrice;
            priceForecast.rise = rise;
            return new Result(ResultCode.SUCCESS, priceForecast);
        } catch (Exception e) {
            e.printStackTrace();
            return new Result(ResultCode.FAIL);
        }
    }

    @ApiOperation(value = "当前房源房价预测", notes = "当前房源房价预测", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "String", name = "houseId", value = "房源ID", required = true, paramType = "path")
    })
    @GetMapping(value = "/currenthomevalueforecast/{houseId}")
    public Object currentHomeValueForecast(@PathVariable String houseId) {

        try {
            House house = listHubService.selectByPrimaryKey(houseId);

            if (house == null)
                return new Result(ResultCode.NO_DATA_WAS_FOUND);
            Double price = house.getListPrice(); //房产价格

            String zip = house.getZip();  //邮编
            String state = house.getProvince();

            //http://youhome.oss-cn-zhangjiakou.aliyuncs.com/zillow/AllRegionsForePublic/ak_zip_99709.json
            //州与邮编不存在
            if (StringUtils.isEmpty(state) || StringUtils.isEmpty(zip)) {
                return new Result(ResultCode.NO_DATA_WAS_FOUND);
            }
            String key = "zillow/AllRegionsForePublic/" + state.toLowerCase() + "_zip_" + zip + ".json";
            System.err.println("key:" + key);
            String json = downloadService.downloadJsonFromOSS(key);
            //没有数据
            if (StringUtils.isEmpty(json)) {
                return new Result(ResultCode.NO_DATA_WAS_FOUND);
            }
            com.alibaba.fastjson.JSONObject jsonObject = JSON.parseObject(json);
            //ForecastYoYPctChange  不存在
            if (jsonObject.get("ForecastYoYPctChange") == null) {
                return new Result(ResultCode.NO_DATA_WAS_FOUND);
            }
            Double rise = Double.valueOf(jsonObject.getString("ForecastYoYPctChange"));

            Double forecastPrice = price * (1 + rise / 100);

            PriceForecast priceForecast = new PriceForecast();
            priceForecast.current_price = price;
            priceForecast.forecast_price = forecastPrice;
            priceForecast.rise = rise;
            return new Result(ResultCode.SUCCESS, priceForecast);
        } catch (Exception e) {
            e.printStackTrace();
            return new Result(ResultCode.FAIL);
        }
    }

    @ApiOperation(value = "房租", notes = "房租", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "String", name = "houseId", value = "房源ID", required = true, paramType = "path"),
            @ApiImplicitParam(dataType = "String", name = "time", value = "时间", required = true, paramType = "query"),
    })
    @GetMapping(value = "/rent/{zipcode}")
    public Object rent(@PathVariable("zipcode") String zipcode, @RequestParam(value = "time") String time) {

        if (time.equals("max")) {
            time = "0";
        }
        try {
            String key = "zillow/Zip_ZriPerSqft_AllHomes/" + zipcode + ".json";
            List<TimeValueItemResult> list = downloadService.downloadTimeValuesFromOSS(key, time);
            if (list == null || list.size() < 1) {
                list = getNextToZipJsonByZips("Zip_ZriPerSqft_AllHomes", zipcode, time);
            }
            return new Result(ResultCode.SUCCESS, list);


        } catch (Exception e) {
            e.printStackTrace();
            return new Result(ResultCode.FAIL);
        }
    }

    @ApiOperation(value = "房价环比", notes = "房价环比", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "String", name = "zipcode", value = "邮编", required = true, paramType = "path"),
            @ApiImplicitParam(dataType = "String", name = "time", value = "时间", required = true, paramType = "query"),
    })
    @GetMapping(value = "/mom/{zipcode}")
    public Object mom(@PathVariable("zipcode") String zipcode, @RequestParam(value = "time") String time) {
        if (time.equals("max")) {
            time = "0";
        }
        try {
//          http://youhome.oss-cn-zhangjiakou.aliyuncs.com/zillow/Zip_Zhvi_AllHomes/01001.json
            String key = "zillow/Zip_Zhvi_AllHomes/" + zipcode + ".json";
            List<TimeValueItemResult> list = downloadService.downloadTimeValuesFromOSS(key);

            //重新获取相邻邮编数据
            if (list == null || list.size() < 1) {
                String type = "Zip_Zhvi_AllHomes";
                list = getNextToZipJsonByZips(type, zipcode);
            }
            List<TimeSeriesItem> moms = new ArrayList<>();
            if (list != null && list.size() > 0) {
                for (int i = 0; i < list.size(); i++) {
                    Date current_time = DateUtils.StrToDate(list.get(i).getTime(), "yyyy-MM");
                    Double current_value = Double.valueOf(list.get(i).getValue()); //当前月的值
                    Date last_month = null;
                    Double last_value = 0.0;
                    if (i > 0) {
                        last_month = DateUtils.StrToDate(list.get(i - 1).getTime(), "yyyy-MM");
                        last_value = Double.valueOf(list.get(i - 1).getValue()); //上月的值
                        Double ratio = 0.0;
                        if (last_value != 0) {
                            //房价环比增长率(moms)  环比增长率=(本期数-上期数)/上期数×100%。
                            ratio = (current_value - last_value) / last_value * 100;
                        }
                        TimeSeriesItem mom = new TimeSeriesItem();
                        mom.setTime(DateUtils.DateToStr(current_time, "yyyy-MM"));
                        mom.setValue(ratio);
                        moms.add(mom);
                    }
                }
            }


            if (!time.equals("0")) {
                String dateFormat = "yyyy-MM";
                Date etime = new Date();
                Date btime = DateUtils.addYear(etime, -Integer.parseInt(time));
                //开始截取的时间
                String startTime = DateUtils.formatDate(btime, dateFormat);
                Boolean flag = false; // 开始截取标识
                List<TimeSeriesItem> items = new ArrayList<>();
                for (TimeSeriesItem item : moms) {
                    if (item.getTime().equalsIgnoreCase(startTime)) {
                        flag = true;  //从这个开始截取
                    }
                    if (flag) {
                        items.add(item);
                    }
                }

                if (items.size() > 0) {
                    return new Result(ResultCode.SUCCESS, items);
                } else {
                    return new Result(ResultCode.NO_DATA_WAS_FOUND);
                }
            } else {
                return new Result(ResultCode.SUCCESS, moms);
            }


        } catch (Exception e) {
            e.printStackTrace();
            return new Result(ResultCode.FAIL);
        }
    }

    @ApiOperation(value = "房价同比增长率", notes = "房价同比增长率", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "String", name = "zipcode", value = "邮编", required = true, paramType = "path"),
            @ApiImplicitParam(dataType = "String", name = "time", value = "时间", required = true, paramType = "query"),
    })
    @GetMapping(value = "/yoy/{zipcode}")
    public Object yoy(@PathVariable("zipcode") String zipcode, @RequestParam(value = "time") String time) {
        if (time.equals("max")) {
            time = "0";
        }
        try {

            //http://youhome.oss-cn-zhangjiakou.aliyuncs.com/zillow/Zip_Zhvi_AllHomes/01001.json
            String key = "zillow/Zip_Zhvi_AllHomes/" + zipcode + ".json";
            List<TimeValueItemResult> list = downloadService.downloadTimeValuesFromOSS(key);
            //重新获取相邻邮编数据
            if (list == null || list.size() < 1) {
                String type = "Zip_Zhvi_AllHomes";
                list = getNextToZipJsonByZips(type, zipcode);
            }
            List<TimeSeriesItem> yoys = new ArrayList<>();
            if (list != null && list.size() > 0) {
                for (int i = 0; i < list.size(); i++) {
                    Date current_time = DateUtils.StrToDate(list.get(i).getTime(), "yyyy-MM");
                    Double current_value = Double.valueOf(list.get(i).getValue()); //当前月的值
                    Date last_month = null;
                    Double last_value = 0.0;
                    if (i > 12) {
                        last_month = DateUtils.StrToDate(list.get(i - 12).getTime(), "yyyy-MM");
                        last_value = Double.valueOf(list.get(i - 12).getValue()); //上年的值
                        Double ratio = 0.0;
                        if (last_value != 0) {
                            //房价环比增长率(moms)  环比增长率=(本期数-上期数)/上期数×100%。
                            ratio = (current_value - last_value) / last_value * 100;
                        }
                        TimeSeriesItem mom = new TimeSeriesItem();
                        mom.setTime(DateUtils.DateToStr(current_time, "yyyy-MM"));
                        mom.setValue(ratio);
                        yoys.add(mom);
                    }
                }
            }

            if (!time.equals("0")) {
                String dateFormat = "yyyy-MM";
                Date etime = new Date();
                Date btime = DateUtils.addYear(etime, -Integer.parseInt(time));
                //开始截取的时间
                String startTime = DateUtils.formatDate(btime, dateFormat);
                Boolean flag = false; // 开始截取标识
                List<TimeSeriesItem> items = new ArrayList<>();
                for (TimeSeriesItem item : yoys) {
                    if (item.getTime().equalsIgnoreCase(startTime)) {
                        flag = true;  //从这个开始截取
                    }
                    if (flag) {
                        items.add(item);
                    }
                }


                if (items.size() > 0) {
                    return new Result(ResultCode.SUCCESS, items);
                } else {
                    return new Result(ResultCode.NO_DATA_WAS_FOUND);
                }
            } else {
                return new Result(ResultCode.SUCCESS, yoys);
            }

        } catch (Exception e) {
            e.printStackTrace();
            return new Result(ResultCode.FAIL);
        }
    }

    @ApiOperation(value = "通勤指数", notes = "通勤指数", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "String", name = "zipcode", value = "邮编", required = true, paramType = "path")
    })
    @GetMapping(value = "/commuteindex/{zipcode}")
    public Object CommuteIndex(@PathVariable("zipcode") String zipcode) {
        try {
            TruliaData truliaData = truliaDataService.selectByZipcode(zipcode);
            CommuteIndex commuteIndex = new CommuteIndex();
            if (truliaData != null) {
                //骑车通勤比例%
                commuteIndex.setBike(truliaData.getCommuteBike());
                //驾车通勤比例%
                commuteIndex.setCar(truliaData.getCommuteCar());
                //步行通勤比例%
                commuteIndex.setFoot(truliaData.getCommuteFoot());
                //公交通勤比例%
                commuteIndex.setTransit(truliaData.getCommuteTransit());
                return new Result(ResultCode.SUCCESS, commuteIndex);
            } else {
                return new Result(ResultCode.NO_DATA_WAS_FOUND);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return new Result(ResultCode.FAIL);
        }
    }

    @ApiOperation(value = "族裔比例", notes = "族裔比例", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "String", name = "zipcode", value = "邮编", required = true, paramType = "path")
    })
    @GetMapping(value = "/populationratio/{zipcode}")
    public Object populationRatio(@PathVariable("zipcode") String zipcode) {
        try {
            CityData cityData = cityDataService.selectByZipcode(zipcode);
            PopulationRatio populationRatio = new PopulationRatio();
            if (cityData != null) {
                //===族裔比例===
                Double indian = cityData.getPopulationAmericanIndian();
                Double black = cityData.getPopulationBlack();
                Double hispanic = cityData.getPopulationHispanic();
                Double islander = cityData.getPopulationIslander();
                Double white = cityData.getPopulationWhite();

                if (indian == null && black == null && hispanic == null && islander == null && white == null) {
                    return new Result(ResultCode.NO_DATA_WAS_FOUND);
                } else {
                    populationRatio.setIndian(indian); //美属印第安人人口
                    populationRatio.setBlack(black); //非裔人口
                    populationRatio.setHispanic(hispanic); //拉丁裔人口
                    populationRatio.setIslander(islander); //太平洋及岛屿人口
                    populationRatio.setWhite(white); //白人人口
                    return new Result(ResultCode.SUCCESS, populationRatio);
                }
            } else {
                return new Result(ResultCode.NO_DATA_WAS_FOUND);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return new Result(ResultCode.FAIL);
        }
    }

    @ApiOperation(value = "平均家庭收入", notes = "平均家庭收入", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "String", name = "zipcode", value = "邮编", required = true, paramType = "path")
    })
    @GetMapping(value = "/averagehouseholdincome/{zipcode}")
    public Object averageHouseholdIncome(@PathVariable("zipcode") String zipcode) {

        try {
            TruliaData truliaData = truliaDataService.selectByZipcode(zipcode);
            ThreePlacesValue threePlacesValue = new ThreePlacesValue();

            if (truliaData != null) {
                //中位家庭收入
                threePlacesValue.setLocal(truliaData.getDemoHouseholdIncome());
                //州平均家庭收入
                //全美平均家庭收入
                threePlacesValue.setAll(USAConfig.getAverage_household_income());

                return new Result(ResultCode.SUCCESS, threePlacesValue);
            } else {
                return new Result(ResultCode.NO_DATA_WAS_FOUND);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return new Result(ResultCode.FAIL);
        }
    }

    @ApiOperation(value = "大学以上教育比例", notes = "大学以上教育比例", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "String", name = "zipcode", value = "邮编", required = true, paramType = "path")
    })
    @GetMapping(value = "/education/{zipcode}")
    public Object education(@PathVariable("zipcode") String zipcode) {
        try {
            TruliaData truliaData = truliaDataService.selectByZipcode(zipcode);
            CityData cityData = cityDataService.selectByZipcode(zipcode);
            ThreePlacesValue threePlacesValue = new ThreePlacesValue();
            if (truliaData != null) {
                //本地大学以上教育比例
                threePlacesValue.setLocal(truliaData.getDemoCollegeEducated());
                //州大学以上教育比例
                threePlacesValue.setState(cityData.getPrivateUndergraduateCollegesState());
                //全美大学以上教育比例
                threePlacesValue.setAll(USAConfig.getUniversity_ratio());
                return new Result(ResultCode.SUCCESS, threePlacesValue);
            } else {
                return new Result(ResultCode.NO_DATA_WAS_FOUND);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return new Result(ResultCode.FAIL);
        }
    }

    @ApiOperation(value = "失业率", notes = "失业率", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "String", name = "zipcode", value = "邮编", required = true, paramType = "path")
    })
    @GetMapping(value = "/unemployed/{zipcode}")
    public Object unemployed(@PathVariable("zipcode") String zipcode) {
        try {
            if (StringUtils.isEmpty(zipcode))
                return new Result(ResultCode.ERROR_PARAMETER);

            CityData cityData = cityDataService.selectByZipcode(zipcode);
            Zip zip = zipService.selectByPrimaryKey(zipcode);
            String state = zip.getState();
            System.err.println("state:" + state);
            Double state_unemployed_rate = unemploymentService.selectRateByUnemployment(1, state);
            ThreePlacesValue threePlacesValue = new ThreePlacesValue();
            System.err.println("zipcode:" + zipcode);
            if (cityData != null) {
                //本地失业率
                threePlacesValue.setLocal(cityData.getUnemployed());
                //州失业率
                if (state_unemployed_rate != null)
                    threePlacesValue.setState(state_unemployed_rate);
                //全美失业率
                threePlacesValue.setAll(USAConfig.getUnemployed());
                return new Result(ResultCode.SUCCESS, threePlacesValue);
            } else {
                return new Result(ResultCode.NO_DATA_WAS_FOUND);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return new Result(ResultCode.FAIL);
        }
    }

    @ApiOperation(value = "蓝领白领比例", notes = "蓝领白领比例", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "String", name = "zipcode", value = "邮编", required = true, paramType = "path")
    })
    @GetMapping(value = "/bluewhitecollar/{zipcode}")
    public Object blueWhiteCollar(@PathVariable("zipcode") String zipcode) {
        BlueWhiteCollar blueWhiteCollar = new BlueWhiteCollar();
        blueWhiteCollar.setBlue(0.99);
        blueWhiteCollar.setWhite(0.01);
        return new Result(ResultCode.SUCCESS, blueWhiteCollar);
    }

    @ApiOperation(value = "1b/2b/3b/4b/5b+房价变化", notes = "1b/2b/3b/4b/5b+房价变化", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "String", name = "zipcode", value = "邮编", required = true, paramType = "path"),
            @ApiImplicitParam(dataType = "String", name = "time", value = "时间", required = true, paramType = "query")
    })
    @GetMapping(value = "/bedroom/{zipcode}")
    public Object bedRoom(@PathVariable("zipcode") String zipcode, @RequestParam(value = "time") String time) {
        if (time.equals("max")) {
            time = "0";
        }
        try {

//            http://youhome.oss-cn-zhangjiakou.aliyuncs.com/zillow/Zip_Zhvi_1bedroom/01001.json
//            http://youhome.oss-cn-zhangjiakou.aliyuncs.com/zillow/Zip_Zhvi_2bedroom/01001.json
//            http://youhome.oss-cn-zhangjiakou.aliyuncs.com/zillow/Zip_Zhvi_3bedroom/01001.json
//            http://youhome.oss-cn-zhangjiakou.aliyuncs.com/zillow/Zip_Zhvi_4bedroom/01001.json
//            http://youhome.oss-cn-zhangjiakou.aliyuncs.com/zillow/Zip_Zhvi_5BedroomOrMore/01001.json
            String key1 = "zillow/Zip_Zhvi_1bedroom/" + zipcode + ".json";
            String key2 = "zillow/Zip_Zhvi_2bedroom/" + zipcode + ".json";
            String key3 = "zillow/Zip_Zhvi_3bedroom/" + zipcode + ".json";
            String key4 = "zillow/Zip_Zhvi_4bedroom/" + zipcode + ".json";
            String key5 = "zillow/Zip_Zhvi_5BedroomOrMore/" + zipcode + ".json";

            List<TimeValueItemResult> results1 = downloadService.downloadTimeValuesFromOSS(key1, time);
            if (results1 == null || results1.size() < 1) {
                results1 = getNextToZipJsonByZips("Zip_Zhvi_1bedroom", zipcode, time);
            }
            List<TimeValueItemResult> results2 = downloadService.downloadTimeValuesFromOSS(key2, time);
            if (results2 == null || results2.size() < 1) {
                results2 = getNextToZipJsonByZips("Zip_Zhvi_2bedroom", zipcode, time);
            }
            List<TimeValueItemResult> results3 = downloadService.downloadTimeValuesFromOSS(key3, time);
            if (results3 == null || results3.size() < 1) {
                results3 = getNextToZipJsonByZips("Zip_Zhvi_3bedroom", zipcode, time);
            }
            List<TimeValueItemResult> results4 = downloadService.downloadTimeValuesFromOSS(key4, time);
            if (results4 == null || results4.size() < 1) {
                results4 = getNextToZipJsonByZips("Zip_Zhvi_4bedroom", zipcode, time);
            }
            List<TimeValueItemResult> results5 = downloadService.downloadTimeValuesFromOSS(key5, time);
            if (results5 == null || results5.size() < 1) {
                results5 = getNextToZipJsonByZips("Zip_Zhvi_5BedroomOrMore", zipcode, time);
            }

            List<TimeSeriesItem> TimeSeriesItems1 = new ArrayList<>();
            for (TimeValueItemResult item : results1) {
                TimeSeriesItem timeSeriesItem = new TimeSeriesItem();
                timeSeriesItem.setTime(item.getTime());
                timeSeriesItem.setValue(Double.valueOf(item.getValue()));
                TimeSeriesItems1.add(timeSeriesItem);
            }

            List<TimeSeriesItem> TimeSeriesItems2 = new ArrayList<>();
            for (TimeValueItemResult item : results2) {
                TimeSeriesItem timeSeriesItem = new TimeSeriesItem();
                timeSeriesItem.setTime(item.getTime());
                timeSeriesItem.setValue(Double.valueOf(item.getValue()));
                TimeSeriesItems2.add(timeSeriesItem);
            }

            List<TimeSeriesItem> TimeSeriesItems3 = new ArrayList<>();
            for (TimeValueItemResult item : results3) {
                TimeSeriesItem timeSeriesItem = new TimeSeriesItem();
                timeSeriesItem.setTime(item.getTime());
                timeSeriesItem.setValue(Double.valueOf(item.getValue()));
                TimeSeriesItems3.add(timeSeriesItem);
            }

            List<TimeSeriesItem> TimeSeriesItems4 = new ArrayList<>();
            for (TimeValueItemResult item : results4) {
                TimeSeriesItem timeSeriesItem = new TimeSeriesItem();
                timeSeriesItem.setTime(item.getTime());
                timeSeriesItem.setValue(Double.valueOf(item.getValue()));
                TimeSeriesItems4.add(timeSeriesItem);
            }

            List<TimeSeriesItem> TimeSeriesItems5 = new ArrayList<>();
            for (TimeValueItemResult item : results5) {
                TimeSeriesItem timeSeriesItem = new TimeSeriesItem();
                timeSeriesItem.setTime(item.getTime());
                timeSeriesItem.setValue(Double.valueOf(item.getValue()));
                TimeSeriesItems5.add(timeSeriesItem);
            }


            if (TimeSeriesItems1.size() == 0 && TimeSeriesItems2.size() == 0 && TimeSeriesItems3.size() == 0 && TimeSeriesItems4.size() == 0 && TimeSeriesItems5.size() == 0) {
                return new Result(ResultCode.NO_DATA_WAS_FOUND);
            }
            BedRoomResult list = new BedRoomResult(TimeSeriesItems1, TimeSeriesItems2, TimeSeriesItems3, TimeSeriesItems4, TimeSeriesItems5);
            return new Result(ResultCode.SUCCESS, list);
        } catch (Exception e) {
            e.printStackTrace();
            return new Result(ResultCode.FAIL);
        }
    }

    @ApiOperation(value = "房产售价中位数比（本地与州）", notes = "房产售价中位数比（本地与州）", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "String", name = "zipcode", value = "邮编", required = true, paramType = "path")
    })
    @GetMapping(value = "/medianhousepriceratio/{zipcode}")
    public Object MedianHousePriceRatio(@PathVariable("zipcode") String zipcode) {
        try {
            TruliaData truliaData = truliaDataService.selectByZipcode(zipcode);
            ThreePlacesValue threePlacesValue = new ThreePlacesValue();
            if (truliaData != null) {
                //本地房产售价中位数
                threePlacesValue.setLocal(truliaData.getMedianSalesPrice());
                //州房产售价中位数
                threePlacesValue.setState(2000000.00);
                return new Result(ResultCode.SUCCESS, threePlacesValue);
            } else {
                return new Result(ResultCode.NO_DATA_WAS_FOUND);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return new Result(ResultCode.FAIL);
        }

    }

    @ApiOperation(value = "家庭中位收入比（本地与州）", notes = "家庭中位收入比（本地与州）", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "String", name = "zipcode", value = "邮编", required = true, paramType = "path")
    })
    @GetMapping(value = "/medianhouseholdincomeratio/{zipcode}")
    public Object medianHouseholdIncomeRatio(@PathVariable("zipcode") String zipcode) {
        try {
            CityData cityData = cityDataService.selectByZipcode(zipcode);
            ThreePlacesValue threePlacesValue = new ThreePlacesValue();
            if (cityData != null) {
                //本地家庭中位收入
                threePlacesValue.setLocal(cityData.getAverageHouseholdIncome2015());
                //州房家庭中位收入
                threePlacesValue.setState(2000000.00);
                return new Result(ResultCode.SUCCESS, threePlacesValue);
            } else {
                return new Result(ResultCode.NO_DATA_WAS_FOUND);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return new Result(ResultCode.FAIL);
        }

    }

    @ApiOperation(value = "房价负担指数（本地与州）", notes = "房价负担指数（本地与州）", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "String", name = "zipcode", value = "邮编", required = true, paramType = "path")
    })
    @GetMapping(value = "/housingaffordabilityindex/{zipcode}")
    public Object housingAffordabilityIndex(@PathVariable("zipcode") String zipcode) {
        try {
            CityData cityData = cityDataService.selectByZipcode(zipcode);
            TruliaData truliaData = truliaDataService.selectByZipcode(zipcode);
            ThreePlacesValue threePlacesValue = new ThreePlacesValue();
            if (cityData != null && truliaData != null) {
                //本地家庭中位收入
                Double local_income = cityData.getAverageHouseholdIncome2015();
                //州房家庭中位收入
                Double state_income = 200000.0;

                //本地房产售价中位数
                Double local_price = truliaData.getMedianSalesPrice();
                //州房产售价中位数
                Double state_price = 2000000.00;

                Double local_ratio = null;
                if (local_price != null && local_income != 0)
                    local_ratio = local_price / local_income;

                Double state_ratio = null;
                if (state_price != null && state_income != 0)
                    state_ratio = state_price / state_income;

                if (local_ratio == null && state_ratio == null) {
                    return new Result(ResultCode.NO_DATA_WAS_FOUND);
                }

                threePlacesValue.setLocal(local_ratio);
                threePlacesValue.setState(state_ratio);

                return new Result(ResultCode.SUCCESS, threePlacesValue);
            } else {
                return new Result(ResultCode.NO_DATA_WAS_FOUND);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return new Result(ResultCode.FAIL);
        }

    }

    @ApiOperation(value = "房租中位数时间图", notes = "房租中位数时间图", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "String", name = "zipcode", value = "邮编", required = true, paramType = "path"),
            @ApiImplicitParam(dataType = "String", name = "time", value = "时间", required = true, paramType = "query")
    })
    @GetMapping(value = "/medianrent/{zipcode}")
    public Object MedianRent(@PathVariable("zipcode") String zipcode, @RequestParam(value = "time") String time) {
        if (time.equals("max")) {
            time = "0";
        }
        try {

            String key = "zillow/Zip_Zri_AllHomesPlusMultifamily/" + zipcode + ".json";
            List<TimeValueItemResult> list = downloadService.downloadTimeValuesFromOSS(key, time);
            //重新获取相邻邮编数据
            if (list == null || list.size() < 1) {
                list = getNextToZipJsonByZips("Zip_Zri_AllHomesPlusMultifamily", zipcode, time);
            }
            return new Result(ResultCode.SUCCESS, list);
        } catch (Exception e) {
            e.printStackTrace();
            return new Result(ResultCode.FAIL);
        }
    }

    @ApiOperation(value = "预估租金", notes = "预估租金", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "String", name = "zipcode", value = "邮编", required = true, paramType = "path"),
            @ApiImplicitParam(dataType = "String", name = "time", value = "时间", required = true, paramType = "query")
    })
    @GetMapping(value = "/rentforecast/{zipcode}")
    public Object RentForecast(@PathVariable("zipcode") String zipcode, @RequestParam(value = "time") String time) {
        return new Result(ResultCode.NO_DATA_WAS_FOUND);
    }

    @ApiOperation(value = "购房指数（压力）", notes = "购房指数（压力）", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "String", name = "zipcode", value = "邮编", required = true, paramType = "path")
    })
    @GetMapping(value = "/affordability/{zipcode}")
    public Object Affordability(@PathVariable("zipcode") String zipcode) {
        try {
            Affordability affordability = new Affordability();
            Zip zip = zipService.selectByPrimaryKey(zipcode);
            if (zip == null)
                return new Result(ResultCode.NO_DATA_WAS_FOUND);
            String metro = zip.getMetro();
            System.err.println("metro:" + metro);
            String price_to_income = "zillow/Affordability_Wide_Public/" + StringUtil.replaceBlankAndComma(metro) + "_price_to_income.json";
            String mortgage_affordability = "zillow/Affordability_Wide_Public/" + StringUtil.replaceBlankAndComma(metro) + "_mortgage_affordability.json";
            String rent_affordability = "zillow/Affordability_Wide_Public/" + StringUtil.replaceBlankAndComma(metro) + "_rent_affordability.json";

            List<TimeValueItemResult> timeValueItemResults_price_to_income = downloadService.downloadTimeValuesFromOSS(price_to_income);
            List<TimeValueItemResult> timeValueItemResults_mortgage_affordability = downloadService.downloadTimeValuesFromOSS(mortgage_affordability);
            List<TimeValueItemResult> timeValueItemResults_rent_affordability = downloadService.downloadTimeValuesFromOSS(rent_affordability);
            System.err.println("timeValueItemResults_price_to_income:" + timeValueItemResults_price_to_income);
            System.err.println("timeValueItemResults_mortgage_affordability:" + timeValueItemResults_mortgage_affordability);
            System.err.println("timeValueItemResults_rent_affordability:" + timeValueItemResults_rent_affordability);

            if (timeValueItemResults_price_to_income != null) {
                affordability.price_to_income = Double.valueOf(timeValueItemResults_price_to_income.get(timeValueItemResults_price_to_income.size() - 1).getValue());
            }
            if (timeValueItemResults_mortgage_affordability != null) {
                affordability.mortgage_affordability = Double.valueOf(timeValueItemResults_mortgage_affordability.get(timeValueItemResults_mortgage_affordability.size() - 1).getValue());
            }
            if (timeValueItemResults_rent_affordability != null) {
                affordability.rent_affordability = Double.valueOf(timeValueItemResults_rent_affordability.get(timeValueItemResults_rent_affordability.size() - 1).getValue());
            }

            return new Result(ResultCode.SUCCESS, affordability);

        } catch (Exception e) {
            e.printStackTrace();
            return new Result(ResultCode.FAIL);
        }
    }

    @ApiOperation(value = "SFR/condo房价变化", notes = "SFR/condo房价变化", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "String", name = "zipcode", value = "邮编", required = true, paramType = "path")
    })
    @GetMapping(value = "/sfrcondo/{zipcode}")
    public Object SFRCondo(@PathVariable("zipcode") String zipcode, @RequestParam(value = "time") String time) {
        if (time.equals("max")) {
            time = "0";
        }
        try {
//            http://youhome.oss-cn-zhangjiakou.aliyuncs.com/zillow/Zip_Zhvi_Condominum/02563.json
//            http://youhome.oss-cn-zhangjiakou.aliyuncs.com/zillow/Zip_Zhvi_SingleFamilyResidence/02061.json
            String key_Zip_Zhvi_Condominum = "zillow/Zip_Zhvi_Condominum/" + zipcode + ".json";
            String key_Zip_Zhvi_SingleFamilyResidence = "zillow/Zip_Zhvi_SingleFamilyResidence/" + zipcode + ".json";
            List<TimeValueItemResult> results_Zip_Zhvi_Condominum = downloadService.downloadTimeValuesFromOSS(key_Zip_Zhvi_Condominum, time);
            if (results_Zip_Zhvi_Condominum == null || results_Zip_Zhvi_Condominum.size() < 1) {
                results_Zip_Zhvi_Condominum = getNextToZipJsonByZips("Zip_Zhvi_Condominum", zipcode, time);
            }
            List<TimeValueItemResult> results_Zip_Zhvi_SingleFamilyResidence = downloadService.downloadTimeValuesFromOSS(key_Zip_Zhvi_SingleFamilyResidence, time);
            if (results_Zip_Zhvi_SingleFamilyResidence == null || results_Zip_Zhvi_SingleFamilyResidence.size() < 1) {
                results_Zip_Zhvi_SingleFamilyResidence = getNextToZipJsonByZips("Zip_Zhvi_SingleFamilyResidence", zipcode, time);
            }

            List<TimeSeriesItem> zip_zhvi_condominum = new ArrayList<>();
            List<TimeSeriesItem> zip_zhvi_singlefamilyresidence = new ArrayList<>();

            if (results_Zip_Zhvi_Condominum != null && results_Zip_Zhvi_Condominum.size() > 0) {
                for (TimeValueItemResult item : results_Zip_Zhvi_Condominum) {
                    TimeSeriesItem timeSeriesItem = new TimeSeriesItem();
                    timeSeriesItem.setTime(item.getTime());
                    timeSeriesItem.setValue(Double.valueOf(item.getValue()));
                    zip_zhvi_condominum.add(timeSeriesItem);
                }
            }
            if (results_Zip_Zhvi_SingleFamilyResidence != null && results_Zip_Zhvi_SingleFamilyResidence.size() > 0) {
                for (TimeValueItemResult item : results_Zip_Zhvi_SingleFamilyResidence) {
                    TimeSeriesItem timeSeriesItem = new TimeSeriesItem();
                    timeSeriesItem.setTime(item.getTime());
                    timeSeriesItem.setValue(Double.valueOf(item.getValue()));
                    zip_zhvi_singlefamilyresidence.add(timeSeriesItem);
                }
            }

            if (zip_zhvi_condominum.size() == 0 && zip_zhvi_singlefamilyresidence.size() == 0) {
                return new Result(ResultCode.NO_DATA_WAS_FOUND);
            }

            SFRCondoResult list = new SFRCondoResult(zip_zhvi_condominum, zip_zhvi_singlefamilyresidence);
            return new Result(ResultCode.SUCCESS, list);

        } catch (Exception e) {
            e.printStackTrace();
            return new Result(ResultCode.FAIL);
        }
    }

    @ApiOperation(value = "房价/租金关系", notes = "房价/租金关系", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "String", name = "zipcode", value = "邮编", required = true, paramType = "path"),
            @ApiImplicitParam(dataType = "String", name = "time", value = "时间", required = true, paramType = "query")
    })
    @GetMapping(value = "/pricerent/{zipcode}")
    public Object pricesRents(@PathVariable("zipcode") String zipcode, @RequestParam(value = "time") String time) {
        if (time.equals("max")) {
            time = "0";
        }
        try {

            //http://youhome.oss-cn-zhangjiakou.aliyuncs.com/zillow/Zip_Zhvi_AllHomes/02061.json
            String key_Zip_Zhvi_AllHomes = "zillow/Zip_Zhvi_AllHomes/" + zipcode + ".json"; //房价
            String key_Zip_Zri_AllHomesPlusMultifamily = "zillow/Zip_Zri_AllHomesPlusMultifamily/" + zipcode + ".json";  //租金
            List<TimeValueItemResult> timeValueItemResults_Zip_Zhvi_AllHomes = downloadService.downloadTimeValuesFromOSS(key_Zip_Zhvi_AllHomes, time);
            if (timeValueItemResults_Zip_Zhvi_AllHomes == null || timeValueItemResults_Zip_Zhvi_AllHomes.size() < 1) {
                timeValueItemResults_Zip_Zhvi_AllHomes = getNextToZipJsonByZips("Zip_Zhvi_AllHomes", zipcode, time);
            }
            List<TimeValueItemResult> timeValueItemResults_Zip_Zri_AllHomesPlusMultifamily = downloadService.downloadTimeValuesFromOSS(key_Zip_Zri_AllHomesPlusMultifamily, time);
            if (timeValueItemResults_Zip_Zri_AllHomesPlusMultifamily == null || timeValueItemResults_Zip_Zri_AllHomesPlusMultifamily.size() < 1) {
                timeValueItemResults_Zip_Zri_AllHomesPlusMultifamily = getNextToZipJsonByZips("Zip_Zri_AllHomesPlusMultifamily", zipcode, time);
            }

            List<TimeSeriesItem> rent_items = new ArrayList<>(); //租金
            List<TimeSeriesItem> price_items = new ArrayList<>();//房价
            List<TimeSeriesItem> rewards = new ArrayList<>();  //租金回报

            if (timeValueItemResults_Zip_Zhvi_AllHomes != null && timeValueItemResults_Zip_Zhvi_AllHomes.size() > 0) {
                for (TimeValueItemResult timeValueItemResult : timeValueItemResults_Zip_Zhvi_AllHomes) {
                    TimeSeriesItem timeSeriesItem = new TimeSeriesItem();
                    timeSeriesItem.setTime(timeValueItemResult.getTime());
                    timeSeriesItem.setValue(Double.valueOf(timeValueItemResult.getValue()));
                    price_items.add(timeSeriesItem);
                }
            }
            if (timeValueItemResults_Zip_Zri_AllHomesPlusMultifamily != null && timeValueItemResults_Zip_Zri_AllHomesPlusMultifamily.size() > 0) {
                for (TimeValueItemResult timeValueItemResult : timeValueItemResults_Zip_Zri_AllHomesPlusMultifamily) {
                    TimeSeriesItem timeSeriesItem = new TimeSeriesItem();
                    timeSeriesItem.setTime(timeValueItemResult.getTime());
                    timeSeriesItem.setValue(Double.valueOf(timeValueItemResult.getValue()));
                    rent_items.add(timeSeriesItem);
                }
            }

            if (rent_items.size() > 0 && price_items.size() > 0) {
                for (TimeSeriesItem rent_item : rent_items) {
                    for (TimeSeriesItem price_item : price_items) {
                        if (rent_item.getTime().compareTo(price_item.getTime()) == 0) {
                            if (rent_item.getValue() != null && price_item.getValue() != null && price_item.getValue() != 0) {
                                TimeSeriesItem timeSeriesItem = new TimeSeriesItem();
                                timeSeriesItem.setTime(rent_item.getTime());
                                // 租金回报 = 租金 * 12 / 房价 * 100
                                double v = rent_item.getValue() * 12 / price_item.getValue() * 100;
                                timeSeriesItem.setValue(v);
                                rewards.add(timeSeriesItem);
                            }
                            break;
                        }
                    }
                }
            }
            if (rent_items.size() > 0 || price_items.size() > 0) {
                PricesRentsResult list = new PricesRentsResult(price_items, rent_items, rewards);
                return new Result(ResultCode.SUCCESS, list);
            } else {
                return new Result(ResultCode.NO_DATA_WAS_FOUND);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return new Result(ResultCode.FAIL);
        }
    }

    @ApiOperation(value = "state/US房价变化", notes = "state/US房价变化", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "String", name = "zipcode", value = "邮编", required = true, paramType = "path"),
            @ApiImplicitParam(dataType = "String", name = "time", value = "时间", required = true, paramType = "query")
    })
    @GetMapping(value = "/stateus/{zipcode}")
    public Object stateUS(@PathVariable("zipcode") String zipcode, @RequestParam(value = "time") String time) {
        if (time.equals("max")) {
            time = "0";
        }

        try {
            Zip zip = zipService.selectByPrimaryKey(zipcode);
            if (zip == null)
                return new Result(ResultCode.NO_DATA_WAS_FOUND);
            String state = zip.getState();
            String metro = zip.getMetro();
            if (!StringUtils.isEmpty(state) && state.length() < 3) {
                state = StateUtils.convert(state);
            }
            //http://youhome.oss-cn-zhangjiakou.aliyuncs.com/zillow/State_Zhvi_AllHomes/missouri.json
            //http://youhome.oss-cn-zhangjiakou.aliyuncs.com/zillow/Metro_Zhvi_AllHomes/fond_du_lac_wi.json
            List<TimeSeriesItem> items_state = new ArrayList<>();
            if (!StringUtils.isEmpty(state)) {
                String key_state = "zillow/State_Zhvi_AllHomes/" + state.toLowerCase() + ".json";
                List<TimeValueItemResult> results_state = downloadService.downloadTimeValuesFromOSS(key_state, time);
                if (results_state != null && results_state.size() > 0) {
                    for (TimeValueItemResult item : results_state) {
                        TimeSeriesItem timeSeriesItem = new TimeSeriesItem();
                        timeSeriesItem.setTime(item.getTime());
                        timeSeriesItem.setValue(Double.valueOf(item.getValue()));
                        items_state.add(timeSeriesItem);
                    }
                }
            }

            List<TimeSeriesItem> items_metro = new ArrayList<>();
            if (!StringUtils.isEmpty(metro)) {
                String key_metro = "zillow/Metro_Zhvi_AllHomes/" + StringUtil.replaceBlankAndComma(metro) + ".json";
                List<TimeValueItemResult> results_metro = downloadService.downloadTimeValuesFromOSS(key_metro, time);
                if (results_metro != null && results_metro.size() > 0) {
                    for (TimeValueItemResult item : results_metro) {
                        TimeSeriesItem timeSeriesItem = new TimeSeriesItem();
                        timeSeriesItem.setTime(item.getTime());
                        timeSeriesItem.setValue(Double.valueOf(item.getValue()));
                        items_metro.add(timeSeriesItem);
                    }
                }
            }

            StateUSResult list = new StateUSResult(items_state, items_metro);

            if (items_state.size() > 0 || items_metro.size() > 0) {
                return new Result(ResultCode.SUCCESS, list);
            } else {
                return new Result(ResultCode.NO_DATA_WAS_FOUND);
            }

        } catch (Exception e) {
            e.printStackTrace();
            return new Result(ResultCode.FAIL);
        }

    }

    @ApiOperation(value = "租金回报", notes = "租金回报", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "String", name = "zipcode", value = "邮编", required = true, paramType = "path"),
            @ApiImplicitParam(dataType = "String", name = "time", value = "时间", required = true, paramType = "query")
    })
    @GetMapping(value = "/rentalyield/{zipcode}")
    public Object rentalYield(@PathVariable("zipcode") String zipcode, @RequestParam(value = "time") String time) {
        if (time.equals("max")) {
            time = "0";
        }
        try {
            String key_Zip_Zhvi_AllHomes = "zillow/Zip_Zhvi_AllHomes/" + zipcode + ".json"; //房价
            String key_Zip_Zri_AllHomesPlusMultifamily = "zillow/Zip_Zri_AllHomesPlusMultifamily/" + zipcode + ".json";  //租金
            List<TimeValueItemResult> timeValueItemResults_Zip_Zhvi_AllHomes = downloadService.downloadTimeValuesFromOSS(key_Zip_Zhvi_AllHomes, time);

            if (timeValueItemResults_Zip_Zhvi_AllHomes == null || timeValueItemResults_Zip_Zhvi_AllHomes.size() < 1) {
                timeValueItemResults_Zip_Zhvi_AllHomes = getNextToZipJsonByZips("Zip_Zhvi_AllHomes", zipcode, time);
            }
            List<TimeValueItemResult> timeValueItemResults_Zip_Zri_AllHomesPlusMultifamily = downloadService.downloadTimeValuesFromOSS(key_Zip_Zri_AllHomesPlusMultifamily, time);
            if (timeValueItemResults_Zip_Zri_AllHomesPlusMultifamily == null || timeValueItemResults_Zip_Zri_AllHomesPlusMultifamily.size() < 1) {
                timeValueItemResults_Zip_Zri_AllHomesPlusMultifamily = getNextToZipJsonByZips("Zip_Zri_AllHomesPlusMultifamily", zipcode, time);
            }
            List<TimeSeriesItem> rent_items = new ArrayList<>(); //租金
            List<TimeSeriesItem> price_items = new ArrayList<>();//房价
            List<TimeSeriesItem> rewards = new ArrayList<>();  //租金回报

            if (timeValueItemResults_Zip_Zhvi_AllHomes != null && timeValueItemResults_Zip_Zhvi_AllHomes.size() > 0) {
                for (TimeValueItemResult timeValueItemResult : timeValueItemResults_Zip_Zhvi_AllHomes) {
                    TimeSeriesItem timeSeriesItem = new TimeSeriesItem();
                    timeSeriesItem.setTime(timeValueItemResult.getTime());
                    timeSeriesItem.setValue(Double.valueOf(timeValueItemResult.getValue()));
                    price_items.add(timeSeriesItem);
                }
            }
            if (timeValueItemResults_Zip_Zri_AllHomesPlusMultifamily != null && timeValueItemResults_Zip_Zri_AllHomesPlusMultifamily.size() > 0) {
                for (TimeValueItemResult timeValueItemResult : timeValueItemResults_Zip_Zri_AllHomesPlusMultifamily) {
                    TimeSeriesItem timeSeriesItem = new TimeSeriesItem();
                    timeSeriesItem.setTime(timeValueItemResult.getTime());
                    timeSeriesItem.setValue(Double.valueOf(timeValueItemResult.getValue()));
                    rent_items.add(timeSeriesItem);
                }
            }

            if (rent_items.size() > 0 && price_items.size() > 0) {
                if (rent_items.size() > 0 && price_items.size() > 0) {
                    for (TimeSeriesItem rent_item : rent_items) {
                        for (TimeSeriesItem price_item : price_items) {
                            if (rent_item.getTime().compareTo(price_item.getTime()) == 0) {
                                if (rent_item.getValue() != null && price_item.getValue() != null && price_item.getValue() != 0) {
                                    TimeSeriesItem timeSeriesItem = new TimeSeriesItem();
                                    timeSeriesItem.setTime(rent_item.getTime());
                                    // 租金回报 = 租金 * 12 / 房价 * 100
                                    double v = rent_item.getValue() * 12 / price_item.getValue() * 100;
                                    timeSeriesItem.setValue(v);
                                    rewards.add(timeSeriesItem);
                                }
                                break;
                            }

                        }
                    }
                }
            }
            if (rewards != null && rewards.size() > 0) {
                return new Result(ResultCode.SUCCESS, rewards);
            } else {
                return new Result(ResultCode.NO_DATA_WAS_FOUND);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return new Result(ResultCode.FAIL);
        }
    }

    @ApiOperation(value = "房源周边学校", notes = "房源周边学校", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "String", name = "grade", value = "年级(1：小,2：初,3：中)", required = true, paramType = "path"),
            @ApiImplicitParam(dataType = "String", name = "zip", value = "邮编", required = true, paramType = "path"),
            @ApiImplicitParam(dataType = "int", name = "pageNumber", value = "页码", required = false, paramType = "query"),
            @ApiImplicitParam(dataType = "int", name = "pageSize", value = "每页条数", required = false, paramType = "query"),
    })
    @GetMapping(value = "/school/{grade}/{zip}")
    public Object school(@PathVariable("grade") Integer grade, @PathVariable("zip") String zip,
                         Integer pageNumber, Integer pageSize) {
        School school = new School();
        school.setZip(zip);
        if (grade == 1) {
            school.setHasElementary(true);
        } else if (grade == 2) {
            school.setHasMiddle(true);
        } else if (grade == 3) {
            school.setHasHigh(true);
        }

        PageInfo<School> list = schoolService.selectByBean(pageNumber, pageSize, school);

        return new ResultPage(ResultCode.SUCCESS, list);
    }


    /**
     * 周边数据-学校
     *
     * @param zip
     * @return
     */
    @ApiOperation(value = "周边数据-学校", notes = "周边数据-学校", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "String", name = "zip", value = "邮编", required = true, paramType = "path")
    })
    @GetMapping(value = "/school/{zip}")
    public Object school(@PathVariable String zip) {
        if (StringUtils.isEmpty(zip)) {
            return new Result(ResultCode.ERROR_PARAMETER);
        }
        com.youhome.result.School school = homeJunctionService.school(zip);
        return new Result(ResultCode.SUCCESS, school);
    }

    @ApiOperation(value = "周边数据-学校详情", notes = "周边数据-学校详情", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "String", name = "id", value = "学校ID", required = true, paramType = "path")
    })
    @GetMapping(value = "/school/detail/{id}")
    public Object schoolDetail(@PathVariable String id) {
        if (StringUtils.isEmpty(id)) {
            return new Result(ResultCode.ERROR_PARAMETER);
        }
        SchoolDetail school = homeJunctionService.schoolDetail(id);
        return new Result(ResultCode.SUCCESS, school);
    }

    @ApiOperation(value = "周边数据", notes = "周边数据", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "String", name = "houseId", value = "房源ID", required = true, paramType = "path")
    })
    @GetMapping(value = "/periphery/{houseId}")
    public Object periphery(@PathVariable String houseId) {
        if (StringUtils.isEmpty(houseId)) {
            return new Result(ResultCode.ERROR_PARAMETER);
        }
        HomeJunction periphery = homeJunctionService.periphery(houseId);
        return new Result(ResultCode.SUCCESS, periphery);
    }


    /***
     * 重新获取相邻邮编数据
     * @param type 文件路径
     * @param zip 邮编
     * @return
     */
    public List<TimeValueItemResult> getNextToZipJsonByZips(String type, String zip) {
        List<TimeValueItemResult> list = new ArrayList<>();
        List<String> zipCodes = zipService.selectSameCityZipsByZip(zip);
        System.err.println("==============>>zipCodes:" + zipCodes.toString());
        if (zipCodes != null && zipCodes.size() > 0) {
            final int len = zipCodes.size();
            for (int i = 0; i < len; i++) {
                String postcode = StringUtil.getZip(zipCodes, zip);
                System.err.println("====相邻zip:" + postcode);
                zipCodes.remove(postcode); //数组中删除与zip 最近的邮编
                String key = "zillow/" + type + "/" + postcode + ".json";
                list = downloadService.downloadTimeValuesFromOSS(key); //重新获取json 数据
                if (list != null && list.size() > 0) {
                    break;
                }
            }
        }
        return list;
    }


    /***
     * 重新获取相邻邮编数据
     * @param type 文件路径
     * @param zip 邮编
     * @return
     */
    public List<TimeValueItemResult> getNextToZipJsonByZips(String type, String zip, String time) {
        List<TimeValueItemResult> list = new ArrayList<>();
        List<String> zipCodes = zipService.selectSameCityZipsByZip(zip);
        System.err.println("==============>>zipCodes:" + zipCodes.toString());
        if (zipCodes != null && zipCodes.size() > 0) {
            final int len = zipCodes.size();
            for (int i = 0; i < len; i++) {
                String postcode = StringUtil.getZip(zipCodes, zip);
                System.err.println("====相邻zip:" + postcode);
                zipCodes.remove(postcode); //数组中删除与zip 最近的邮编
                String key = "zillow/" + type + "/" + postcode + ".json";
                list = downloadService.downloadTimeValuesFromOSS(key, time); //重新获取json 数据
                if (list != null && list.size() > 0) {
                    break;
                }
            }
        }
        return list;
    }

}
